package cmd

import (
	"errors"
	"fmt"
	"gexcel/pkg/common"
	"gexcel/pkg/excel"
	"strings"

	log "github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
)

var FilePath string
var Sheet string
var Start int
var End int
var Columns string
var IsNoHead bool
var IsNoIdx bool
var IsNoIdxRow bool
var IsNoIdxCol bool

func init() {
	GetCmd.Flags().StringVarP(&Sheet, "sheet", "s", "", "指定要读取的工作表名称")
	GetCmd.Flags().IntVarP(&Start, "start", "", 1, "指定读取的开始行号 (从1开始)")
	GetCmd.Flags().IntVarP(&End, "end", "", -1, "指定读取的结束行号 (包含该行)")
	GetCmd.Flags().StringVarP(&Columns, "columns", "c", "", "指定要显示的列 (支持列号 \"A,B\" 或表头名 \"Name,Age\")")
	GetCmd.Flags().BoolVarP(&IsNoHead, "no-header", "", false, "输出结果中不包含第一行表头")
	GetCmd.Flags().BoolVarP(&IsNoIdx, "no-idx", "", false, "隐藏所有索引 (同时隐藏行号和列标)")
	GetCmd.Flags().BoolVarP(&IsNoIdxRow, "no-idx-row", "", false, "仅隐藏行号 (Row Number)")
	GetCmd.Flags().BoolVarP(&IsNoIdxCol, "no-idx-col", "", false, "仅隐藏列标 (A, B, C...)")
	rootCmd.AddCommand(GetCmd)
}

var GetCmd = &cobra.Command{
	Use:     "get",
	Aliases: []string{"select"},
	Short:   "查询数据",
	Long:    "从Excel文件中提取数据，支持范围切片和列筛选",
	Example: `  gexcel get data.xlsx
  gexcel get data.xlsx --end 10
  gexcel get data.xlsx --start 20 --end 50
  gexcel get data.xlsx --sheet "Sales" --start 5 --end 15
  gexcel get data.xlsx --columns "A,C"
  gexcel get data.xlsx --columns "ID,Price" --end 20
  gexcel get data.xlsx --start 2 --end 100 --no-header --no-idx`,
	Args: func(cmd *cobra.Command, args []string) error {
		if len(args) == 0 {
			return errors.New("需要指定表格文件路径！")
		}
		if len(args) > 1 {
			return errors.New("暂时仅支持打开一个表格文件！")
		}
		FilePath = args[0]
		return nil
	},
	Run: func(cmd *cobra.Command, args []string) {
		// 如果设置了--no-idx，则同时设置--no-idx-row和--no-idx-col
		if IsNoIdx {
			IsNoIdxRow = true
			IsNoIdxCol = true
		}

		e := excel.NewExcel(FilePath)
		defer func(e *excel.Excel) {
			_ = e.Close()
		}(e)

		// 如果没有指定Sheet，则显示Sheet列表
		if Sheet == "" {
			sheetList := e.GetSheetList()
			if len(sheetList) == 0 {
				log.Error("文件中没有找到任何工作表")
				return
			}
			// 如果只有一个Sheet，直接使用它
			if len(sheetList) == 1 {
				Sheet = sheetList[0]
			} else {
				// 显示所有Sheet名称
				fmt.Println("工作表列表:")
				for i, name := range sheetList {
					fmt.Printf("  %d: %s\n", i+1, name)
				}
				return
			}
		}

		// 获取数据
		allData, err := e.GetSheetData(excel.Filter{Sheet: Sheet})
		if err != nil {
			log.Errorf("获取工作表数据失败: %v", err)
			return
		}

		if len(allData) == 0 {
			fmt.Println("工作表为空")
			return
		}

		// 处理Start和End参数
		startIndex := Start - 1 // 转换为0基索引
		if startIndex < 0 {
			startIndex = 0
		}
		if startIndex >= len(allData) {
			fmt.Println("起始行超出数据范围")
			return
		}

		endIndex := End
		if endIndex == -1 || endIndex > len(allData) {
			endIndex = len(allData)
		}
		if endIndex <= startIndex {
			fmt.Println("结束行必须大于起始行")
			return
		}

		// 提取指定范围的数据
		data := allData[startIndex:endIndex]

		// 处理列筛选
		var selectedData [][]string
		var header []string
		if Columns != "" {
			selectedData, header = filterColumns(data, Columns, allData[0])
		} else {
			selectedData = data
			if len(allData) > 0 && startIndex == 0 {
				header = allData[0]
			}
		}

		// 打印数据
		printData(selectedData, header)
	},
}

// filterColumns 根据列参数筛选数据
func filterColumns(data [][]string, columnsStr string, header []string) ([][]string, []string) {
	columns := strings.Split(columnsStr, ",")
	selectedIndices := make([]int, 0)
	selectedHeader := make([]string, 0)

	// 解析列参数，支持列号(A,B)和列名(Name,Age)
	for _, col := range columns {
		col = strings.TrimSpace(col)
		found := false

		// 尝试解析为列号（如A,B,C）
		colIndex := common.LettersToNumber(col)
		if colIndex >= 0 && colIndex < len(header) {
			selectedIndices = append(selectedIndices, colIndex)
			selectedHeader = append(selectedHeader, header[colIndex])
			found = true
		} else {
			// 按列名查找
			for i, h := range header {
				if strings.TrimSpace(h) == col {
					selectedIndices = append(selectedIndices, i)
					selectedHeader = append(selectedHeader, h)
					found = true
					break
				}
			}
		}

		if !found {
			// 如果列未找到，添加空列
			selectedIndices = append(selectedIndices, -1)
			selectedHeader = append(selectedHeader, col)
		}
	}

	// 根据选定的列索引提取数据
	selectedData := make([][]string, len(data))
	for i, row := range data {
		newRow := make([]string, len(selectedIndices))
		for j, idx := range selectedIndices {
			if idx >= 0 && idx < len(row) {
				newRow[j] = row[idx]
			} else {
				newRow[j] = ""
			}
		}
		selectedData[i] = newRow
	}

	return selectedData, selectedHeader
}

// printData 打印数据
func printData(data [][]string, header []string) {
	if len(data) == 0 {
		return
	}

	// 是否显示表头
	showHeader := !IsNoHead && len(header) > 0
	// 是否显示行号
	showRowIdx := !IsNoIdxRow
	// 是否显示列标
	showColIdx := !IsNoIdxCol

	// 计算每列的最大宽度
	colWidths := make([]int, len(data[0]))
	if showHeader {
		for i, h := range header {
			if i < len(colWidths) && len(h) > colWidths[i] {
				colWidths[i] = len(h)
			}
		}
	}

	for _, row := range data {
		for i, cell := range row {
			if i < len(colWidths) && len(cell) > colWidths[i] {
				colWidths[i] = len(cell)
			}
		}
	}

	// 确保最小宽度为1
	for i := range colWidths {
		if colWidths[i] < 1 {
			colWidths[i] = 1
		}
	}

	// 打印列标
	if showColIdx {
		if showRowIdx {
			fmt.Print(strings.Repeat(" ", 4)) // 为行号留出空间
		}
		for i := 0; i < len(colWidths); i++ {
			colName := common.NumberToLetters(i)
			fmt.Printf("%-*s ", colWidths[i], colName)
		}
		fmt.Println()
	}

	// 打印表头
	if showHeader {
		if showRowIdx {
			fmt.Print("Hdr ") // 表头标识
		}
		for i, h := range header {
			if i < len(colWidths) {
				fmt.Printf("%-*s ", colWidths[i], h)
			}
		}
		fmt.Println()
	}

	// 打印数据行
	for i, row := range data {
		if showRowIdx {
			rowNum := Start + i
			fmt.Printf("%-4d", rowNum)
		}
		for j, cell := range row {
			if j < len(colWidths) {
				fmt.Printf("%-*s ", colWidths[j], cell)
			}
		}
		fmt.Println()
	}
}
